/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.moderatorplugin;

import java.io.File;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import com.pearreview.application.Messages;
import com.pearreview.util.review.Attendee;
import com.pearreview.util.review.Meeting;
import com.pearreview.util.review.Review;

public class DirectoryInvitationPackageCreator extends
		AbstractInvitationCreator implements InvitationPackageCreator {
	private static final long serialVersionUID = -4382788875965366884L;
	
	public static final int READ_FILE_BUFFER_SIZE = 4 * 1024;
	
	private boolean attachFiles;
	
	/**
	 * Returns localized string of this component
	 * @param key key of string to localize
	 * @return localized string of this component
	 */
	private static String getLocalizedString(String key) {
		return Messages.getString("PearReview.invitation." + key);
	}
	
	public DirectoryInvitationPackageCreator() {
		this(true);
	}
	
	public DirectoryInvitationPackageCreator(boolean attachFiles) {
		this.setAttachFiles(attachFiles);
	}

	@Override
	public void create(Review review, List<Meeting> meetings, File dir,
			InvitationDocumentCreator creator) throws Exception {

		if(review.getAttendees() == null)
			return;
		
		for(Attendee attendee: review.getAttendees()) {
			File attendeeDir = new File(dir, attendee.getName());
			File attendeeFile = new File(attendeeDir, 
					getLocalizedString("invitation") + 
					creator.getFileExtension());
			attendeeFile = getFreeFile(attendeeFile);
			
			attendeeDir.mkdirs();
			
			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(attendeeFile);
				creator.create(review, meetings, attendee, fos);
				
				if(isAttachFiles() && review.getProduct() != null) {
					String referenceDir = getLocalizedString("references");
					File attendeReferenceDir = 
							new File(attendeeDir, referenceDir);
					attachFiles(attendeReferenceDir, 
							review.getProduct().getReference());
				}
			} catch(Exception e) {
				throw e;
			} finally {
				try {
					if(fos != null)
						fos.close();
				} catch(Throwable e) {
					
				}
			}
		}
	}

	/**
	 * Copies files to dir
	 * @param dir
	 * @param lst
	 * @throws IOException 
	 */
	protected void attachFiles(File dir, List<String> lst) 
			throws IOException {
		List<String> fileList = this.getFileList(lst);
		
		if(fileList == null)
			return;
		
		for(String ref: fileList) {
			File source = getFile(ref);
			File target = new File(dir, source.getName());
			
			target.getParentFile().mkdirs();
			
			copyFile(source, target);
		}
	}
	
	/**
	 * Copies file
	 * @param source
	 * @param target
	 * @throws IOException
	 */
	protected void copyFile(File source, File target) throws IOException {
		FileInputStream input = null;
		FileOutputStream output = null;
		try {
			input = new FileInputStream(source);
			output = new FileOutputStream(getFreeFile(target));
			
			byte[] buffer = new byte[READ_FILE_BUFFER_SIZE];
			
			int len;
			while((len = input.read(buffer)) > 0) {
				output.write(buffer, 0, len);
			}
		} catch(IOException e) {

			throw e;
		} finally {
			try {
				if(input != null)
					input.close();
			} catch(Throwable e1) {
				
			}
			try {
				if(output != null)
					output.close();
			} catch(Throwable e1) {
				
			}
		}
	}

	public void setAttachFiles(boolean attachFiles) {
		this.attachFiles = attachFiles;
	}
	public boolean isAttachFiles() {
		return attachFiles;
	}
}
